//package net.xmmpp.uc.gateway.filter;
//
////import org.apache.commons.lang.StringUtils;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.Ordered;
//import org.springframework.core.io.buffer.DataBuffer;
//import org.springframework.core.io.buffer.DataBufferUtils;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
//import org.springframework.util.MultiValueMap;
//import org.springframework.web.server.ServerWebExchange;
//import org.springframework.web.util.UriComponentsBuilder;
//import reactor.core.publisher.Flux;
//import reactor.core.publisher.Mono;
//
//import java.io.IOException;
//import java.net.URI;
//import java.nio.charset.StandardCharsets;
//import java.time.LocalDateTime;
//import java.util.*;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
//@Configuration
////@ConditionalOnProperty(value = "log.request.enabled", havingValue = "true", matchIfMissing = true)
//public class RequestLogFilter implements GlobalFilter, Ordered {
//
//    private static final Logger LOGGER = LoggerFactory.getLogger(RequestLogFilter.class);
//
//    /**
//     * 网关不是基于springmvc的,而是基于webflux去做的
//     * SpringCloudGateway中Post请求参数只能读取一次
//     * 这是因为Gateway默认使用的是SpringWebflux，解决这个问题需要容重新构造一个request来替换原先的request
//     *
//     * CacheBodyGlobalFilter这个全局过滤器把原有的request请求中的body内容读出来，并且使用ServerHttpRequestDecorator这个请求装饰器对request进行包装，重写getBody方法，并把包装后的请求放到过滤器链中传递下去。这样后面的过滤器中再使用exchange.getRequest().getBody()来获取body时，实际上就是调用的重载后的getBody方法，获取的最先已经缓存了的body数据。这样就能够实现body的多次读取了。
//     * //过滤器的Ordered.HIGHEST_PRECEDENCE，即最高优先级的过滤器。优先级设置高的原因是某些系统内置的过滤器可能也会去读body。
//     *
//     *
//     * https://blog.csdn.net/qq_19636353/article/details/126759522
//     *
//     * @param exchange
//     * @param chain
//     * @return
//     */
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        ServerHttpRequest request = exchange.getRequest();
//        URI requestURI = request.getURI();
///*
//        if (requestURI.startsWith("/actuator")) {
//            chain.filter(exchange);
//            return null;
//        }
//        */
//
////        String path = request.getPath().value();
//        String path = request.getPath().pathWithinApplication().value();//打印请求路径
//        String requestUrl = this.getOriginalRequestUrl(exchange);//打印请求url
//        String method = request.getMethodValue();
//
//        Flux<DataBuffer>  bufferFlux = request.getBody();
//
//        StringBuilder strBuilder = new StringBuilder();
//        strBuilder.append("Request start at: ").append(LocalDateTime.now()).append('\n')
//                .append("Request url: ").append(requestUrl).append('\n')
//                .append("Request method: ").append(method).append('\n')
//                .append("Request headers: ").append('\n');
//
//        //cors
//        HttpHeaders headers = request.getHeaders();
//        for(Map.Entry<String, List<String>> entry : headers.entrySet()){
//            strBuilder.append('\t').append(entry.getKey()).append(": ").append(entry.getValue()).append('\n');
//        }
//
//
//        MultiValueMap<String, String> queryParams = request.getQueryParams();
//        strBuilder.append("Request query string: ").append(queryParams).append('\n');
//
//        if ("POST".equals(method)) {
//            return DataBufferUtils.join(exchange.getRequest().getBody())
//                    .flatMap(dataBuffer -> {
//                        byte[] bytes = new byte[dataBuffer.readableByteCount()];
//                        dataBuffer.read(bytes);
//                        String bodyString = new String(bytes, StandardCharsets.UTF_8);
//                        strBuilder.append("Request body: ").append(bodyString).append('\n');
//
//                        LOGGER.info(strBuilder.toString());
//
//                        DataBufferUtils.release(dataBuffer);
//                        Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
//                            DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
//                            return Mono.just(buffer);
//                        });
//
//                        ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(request) {
//                            @Override
//                            public Flux<DataBuffer> getBody() {
//                                return cachedFlux;
//                            }
//                        };
//
//                        return chain.filter(exchange.mutate().request(mutatedRequest).build());
//                    });
//        } else if ("GET".equals(method)) {
//            strBuilder.append("Request query string: ").append(queryParams).append('\n');
//            LOGGER.info(strBuilder.toString());
//
//            return chain.filter(exchange);
//        }
//
//        LOGGER.info(strBuilder.toString());
//
//        return chain.filter(exchange);
//    }
//
///*
//    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
//
//        HttpServletRequestExt request = new HttpServletRequestExt(httpServletRequest);
//        String requestURI = request.getRequestURI();
//
//        if (requestURI.startsWith("/actuator")) {
//            filterChain.doFilter(request, httpServletResponse);
//            return;
//        }
//
//        StringBuilder strBuilder = new StringBuilder();
//        strBuilder.append("Request start at: ").append(LocalDateTime.now()).append('\n')
//                .append("Request url: ").append(requestURI).append('\n')
//                .append("Request method: ").append(request.getMethod()).append('\n')
//                .append("Request headers: ").append('\n');
//
//        final Enumeration<String> headerNames = request.getHeaderNames();
//        String headerName = null;
//        String headerValue = null;
//        while (headerNames.hasMoreElements()) {
//            headerName = headerNames.nextElement();
//            headerValue = request.getHeader(headerName);
//            strBuilder.append('\t').append(headerName).append(": ").append(headerValue).append('\n');
//        }
//
//        strBuilder.append("Request query string: ").append(request.getQueryString()).append('\n')
//                .append("Request body: ").append(new String(request.body)).append('\n');
//
//        if (!request.getMethod().equalsIgnoreCase("HEAD")) {
//            LOGGER.info(strBuilder.toString());
//        }
//
//        filterChain.doFilter(request, httpServletResponse);
//    }
//    */
//
//    private String getOriginalRequestUrl(ServerWebExchange exchange) {
//        ServerHttpRequest req = exchange.getRequest();
//        LinkedHashSet<URI> uris = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
//        URI requestUri = uris.stream().findFirst().orElse(req.getURI());
//        MultiValueMap<String, String> queryParams = req.getQueryParams();
//
//        return requestUri.toString();
//    }
//
//    @Override
//    public int getOrder() {
//        return Ordered.LOWEST_PRECEDENCE;
//    }
//
//    private static String formatStr(String str) {
//        if (str != null && str.length() > 0) {
//            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
//            Matcher m = p.matcher(str);
//            return m.replaceAll("");
//        }
//
//        return str;
//    }
//
//    public Mono<Void> filter1(ServerWebExchange exchange, GatewayFilterChain chain) {
//        ServerHttpRequest request = exchange.getRequest();
//        // 打印请求路径
//        String path = request.getPath().pathWithinApplication().value();
//        // 打印请求url
//        String requestUrl = this.getOriginalRequestUrl(exchange);
//
//        // **构建成一条长 日志，避免并发下日志错乱**
//        StringBuilder reqLog = new StringBuilder(200);
//        // 日志参数
//        List<Object> reqArgs = new ArrayList<>();
//        reqLog.append("\n\n================ Gateway Request Start  ================\n");
//        // 打印路由添加占位符
//        reqLog.append("===> {}: {}\n");
//        // 参数
//        String requestMethod = request.getMethodValue();
//        reqArgs.add(requestMethod);
//        reqArgs.add(requestUrl);
//
//        // 打印请求头
//        reqLog.append("===Headers===  {}: {}\n");
//
//        HttpHeaders headers = request.getHeaders();
//        headers.forEach((headerName, headerValue) -> {
//            reqArgs.add(headerName);
//            //如果有token，可以先把token解析后打印出原始报文，JwtUtil替换成自己项目里工具类
////            if (AUTH_KEY.toLowerCase().equals(headerName)) {
////                String value = headerValue.get(0);
////                String token = JwtUtil.getToken(value);
////                Claims claims = JwtUtil.parseJWT(token);
////                reqArgs.add((claims == null) ? "" : claims.toString());
////                reqLog.append("===Headers===  {}: {}\n");
////                reqArgs.add(headerName.concat("-original"));
////                reqArgs.add(StringUtils.join(headerValue.toArray()));
////            } else {
///*
//            reqArgs.add(StringUtils.join(headerValue.toArray()));
//        */
////            }
//        });
//
//        reqLog.append("================  Gateway Request End  =================\n");
//        // 打印执行时间
//        LOGGER.info(reqLog.toString());
//
//        return chain.filter(exchange);
//    }
//
//    private String getOriginalRequestUrl1(ServerWebExchange exchange) {
//        ServerHttpRequest request = exchange.getRequest();
//        LinkedHashSet<URI> uris = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
//        URI requestUri = uris.stream().findFirst().orElse(request.getURI());
//        MultiValueMap<String, String> queryParams = request.getQueryParams();
//
//        return UriComponentsBuilder.fromPath(requestUri.getRawPath()).queryParams(queryParams).build().toUriString();
//    }
//}
